package com.llbnk.springcoding.service;

import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.llbnk.springcoding.loader.LoaderFunction;
import com.llbnk.springcoding.loader.LoaderName;
import com.llbnk.springcoding.loader.TestLoader;
import com.llbnk.springcoding.pojo.TestInform;
import org.apache.commons.collections4.CollectionUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class TestService {

    @Resource
    private TestLoader testLoader;

    // 默认加载项
    public static final List<String> TEST_LOADER_LIST = Lists.newArrayList(
            LoaderName.TEST_ONE_NAME
    );

    public static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
            10,
            10,
            60,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(1000),
            new ThreadFactoryBuilder().setNameFormat("TestService-%d").build(),
            new ThreadPoolExecutor.DiscardPolicy());


    public TestInform getInform(String name) throws JSONException {
        // 前置条件
        JSONObject input = new JSONObject();
        input.put("name",name);

        // 获取加载项
        List<LoaderFunction> loads
                = TEST_LOADER_LIST.stream()
                .map(t -> testLoader.getFunction(t))
                .collect(Collectors.toList());

        TestInform testInform = new TestInform();

        CompletableFuture[] completableFutures = Lists
                .partition(loads, 5)
                .stream()
                .filter(CollectionUtils::isNotEmpty)
                .map(t -> AsyncTaskLoaders(t, input, testInform))
                .flatMap(Collection::stream)
                .toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(completableFutures).join();
        return testInform;
    }

    //异步执行task方法
    private List<CompletableFuture> AsyncTaskLoaders(List<LoaderFunction> tasks, JSONObject input, TestInform testInform) {
        List<CompletableFuture> completableFutures = tasks.stream()
                .map(
                        t -> CompletableFuture.supplyAsync(
                                () -> {
                                    try {
                                        t.apply(input, testInform);
                                    } catch (JSONException e) {
                                        System.out.println(e.getMessage());
                                    }
                                    return null;
                                },
                                THREAD_POOL_EXECUTOR)
                ).collect(Collectors.toList());
        return completableFutures;
    }

}